const fs = require('fs')
const path = require('path')
const express = require('express')
const serveStatic = require('serve-static');
const { createServer: createViteServer } = require('vite')

const isProd = process.env.NODE_ENV === 'production'

async function createServer() {
	const app = express()
	const vite = await createViteServer({
		server: { middlewareMode: 'ssr' }
	})
	if(!isProd){
		// vite = await createViteServer({
		// 	server: { middlewareMode: 'ssr' }
		// })
		// 使用 vite 的 Connect 实例作为中间件
		app.use(vite.middlewares)
	}else{
		app.use(serveStatic(path.resolve(__dirname, './dist/client'), { index: false }));
	}

	app.use('*', async (req, res) => {
		const url = req.originalUrl
		let template;
		let render;
		try {
			if(!isProd){
				// 1. 读取 index.html
				template = fs.readFileSync(
					path.resolve(__dirname, 'index.html'),
					'utf-8'
				)

				// 2. 应用 Vite HTML 转换。这将会注入 Vite HMR 客户端，
				//    同时也会从 Vite 插件应用 HTML 转换。
				//    例如：@vitejs/plugin-react-refresh 中的 global preambles
				template = await vite.transformIndexHtml(url, template)

				// 3. 加载服务器入口。vite.ssrLoadModule 将自动转换
				//    你的 ESM 源码使之可以在 Node.js 中运行！无需打包
				//    并提供类似 HMR 的根据情况随时失效。
				render = (await vite.ssrLoadModule('/src/entry-server.ts')).render
			}else{
				template = fs.readFileSync(
					path.resolve(__dirname, './dist/client/index.html'),
					'utf-8'
				)

				render = require('./dist/server/entry-server.js').render
			}

			// 4. 渲染应用的 HTML。这假设 entry-server.js 导出的 `render`
			//    函数调用了适当的 SSR 框架 API。
			//    例如 ReactDOMServer.renderToString()
			const manifest = require('./dist/client/ssr-manifest.json');
			const { appHtml, state, preloadLinks='' } = await render(url, manifest)
			// 5. 注入渲染后的应用程序 HTML 到模板中。
			const { info } = state
			const { title: baseTitle = "", keywords:baseKeywords='', description:baseDescription=""  } = info || {}
			const { meta } = state.route
			const { title, keywords, description } = meta

			const endTitle = baseTitle?baseTitle:title;
			const endKeywords = baseKeywords?baseKeywords:keywords;
			const endDescription = baseDescription?baseDescription:description;
			const html = template
				.replace(`<!--preload-links-->`, preloadLinks)
				.replace(`<!--ssr-outlet-->`, appHtml)
				.replace('\'<!--pinia-state-->\'', JSON.stringify(state))
				.replace('<title>', `<title>${endTitle}`)
				.replace('<meta name="keywords" content="" />', `<meta name="keywords" content="${endKeywords}" />`)
				.replace('<meta name="description" content="" />', `<meta name="description" content="${endDescription}" />`)

			// 6. 返回渲染后的 HTML。
			res.status(200).set({ 'Content-Type': 'text/html' }).end(html)
		} catch (e) {
			// 如果捕获到了一个错误，让 Vite 来修复该堆栈，这样它就可以映射回
			// 你的实际源码中。
			vite.ssrFixStacktrace(e)
			console.error(e)
			res.status(500).end(e.message)
		}
	})

	app.listen(3000,()=>{
		console.log('Serve 启动成功...:3000',isProd?'生产环境':'开发环境');
	})
}

createServer()